#include "../../include/pool/threadpool.h"

#include <vector>
#include <queue>
#include <memory>
#include <atomic>
#include <functional>
#include <mutex>
#include <condition_variable>
#include <iostream>
#include <chrono>
#include <thread> // c++11 线程启动

const int TASK_MAX_SIZE = 1024;
const int THREAD_MAX_SIZE = 10;
const int THREAD_MAX_IDLE_SECONDS = 60; // 单位s
// 线程池构造
ThreadPool::ThreadPool() : initThreadSize_(4), taskSize_(0), maxTaskSize_(TASK_MAX_SIZE), mode_(PoolMode::FIXED), isPoolRunning_(false), idleThreadSize_(0), maxThreadSize_(THREAD_MAX_SIZE), currentThreadSize_(0)
{
}

ThreadPool::~ThreadPool()
{
    isPoolRunning_ = false;
    // 等待状态->阻塞状态->就绪状态->等待状态
    // 等待线程池里面所有的线程返回，两种状态：，有两种状态：阻塞&正在执行任务中
    std::cout<< "~ThreadPool()"  <<std::endl; 
    std::unique_lock<std::mutex> lock(taskQueLock_);
    notEmpty_.notify_all();
    exitCon_.wait(lock, [&]() -> bool
                  { return threads_.size() == 0; }); 
    std::cout<< "~ThreadPool1()"  <<std::endl;           
}
// 开启线程池
void ThreadPool::start(int intThreadSize)
{
    initThreadSize_ = intThreadSize;
    currentThreadSize_ = intThreadSize;
    isPoolRunning_ = true;
    // 创建线程对象，
    for (int i = 0; i < initThreadSize_; i++)
    {
        // 创建thread线程对象时，把线程函数给到thread线程对象
        auto ptr = std::make_unique<Thread>(std::bind(&ThreadPool::threadFunc, this, std::placeholders::_1));
        int threadId = ptr->getThreadId();
        threads_.emplace(threadId, std::move(ptr)); // 左值引用和右值引用拷贝构造函数?
        // threads_.emplace_back(new Thread(std::bind(&ThreadPool::threadFunc,this)));  //emplace_back 相比push_back减少创建临时变量
    };

    // 启动所有线程
    for (int i = 0; i < initThreadSize_; i++)
    {
        threads_[i]->start();
        idleThreadSize_++;
    }
};

bool ThreadPool::checkRuningState()
{
    return isPoolRunning_;
}

void ThreadPool::setMode(PoolMode mode)
{
    if (checkRuningState())
    {
        return;
    }
    mode_ = mode;
}; // 设置线程池模式

void ThreadPool::setMaxTaskSize(int maxTaskSize)
{
    if (checkRuningState())
    {
        return;
    }
    maxTaskSize_ = maxTaskSize;
}; // 设置线程池最大线程数

// 使用者生产任务，生产者！！！！！！！
Result ThreadPool::submitTask(std::shared_ptr<Task> sp)
{
    // 获取锁
    std::unique_lock<std::mutex> lock(taskQueLock_);
    // lambda表达式
    //[&](//参数)->bool//返回值{
    //    return taskSize_ < maxTaskSize_;
    // }
    // 线程的通信，等待任务队列有空余
    // 用户提交任务，最长不能阻塞超过1s，否则判断提交任务失败，返回
    if (!notFull_.wait_for(lock, std::chrono::seconds(1), [&]() -> bool
                           { return taskSize_ < maxTaskSize_; }))
    {
        std::cout << "timeout" << std::endl;
        // return task-> result 不可行，随着task执行完，task对象没了，task->result也没了
        return Result(sp, false);
    };
    // 如果有空余，放入任务队列
    taskQueue_.emplace(sp);
    taskSize_++;
    // 在notEmpty上通知
    notEmpty_.notify_all();

    if (mode_ == PoolMode::CACHED && taskSize_ > idleThreadSize_ && currentThreadSize_ < maxThreadSize_)
    {
        // 创建新线程
        auto ptr = std::make_unique<Thread>(std::bind(&ThreadPool::threadFunc, this, std::placeholders::_1));
        int threadId = ptr->getThreadId();
        threads_.emplace(threadId, std::move(ptr));
        threads_[threadId]->start();
        idleThreadSize_++;
        currentThreadSize_++;
    }
    return Result(sp, true);
};

// 线程函数,线程池消费任务，消费者！！！！！！！！！！！！！！！
void ThreadPool::threadFunc(int threadId) // 线程函数结束，线程也结束
{
    auto lastTime = std::chrono::high_resolution_clock().now();
    // 线程死循环
    for(;;)
    {
        std::shared_ptr<Task> task;
        {
            // 先获取锁
            std::unique_lock<std::mutex> lock(taskQueLock_);
            while (taskQueue_.size() == 0)
            {

                 //线程池结束，回收线程资源
             if(!isPoolRunning_){
                threads_.erase(threadId); // 删除线程对象
                std::cout << "threadid:" << threadId <<"exit" << std::endl;
                exitCon_.notify_all();
                return;
            }
                // cached模式下，有可能已经创建了很多线程，但是空闲时间超过60s
               // 结束回收掉（超过初始的线程数量）
                if (mode_ == PoolMode::CACHED)
                {
                    if (std::cv_status::timeout == notEmpty_.wait_for(lock, std::chrono::seconds(1)))
                    {
                        auto now = std::chrono::high_resolution_clock().now();
                        auto dur = std::chrono::duration_cast<std::chrono::seconds>(now - lastTime);
                        if (dur.count() > THREAD_MAX_IDLE_SECONDS && currentThreadSize_ > idleThreadSize_)
                        {
                            // 开始回收线程
                            // 记录线程数量的相关变量的值的修改
                            // 把线程对象从线程列表容器中删除
                            // threadid_
                            threads_.erase(threadId); // 删除线程对象
                            currentThreadSize_--;
                            idleThreadSize_--;
                            std::cout << "threadid:" << std::this_thread::get_id() <<"exit" << std::endl;
                            return;
                        }
                    }
                }
                else
                {
                    notEmpty_.wait(lock);
                }
            }
            idleThreadSize_--;
            // 从任务队列取一个任务出来
            task = taskQueue_.front();
            taskQueue_.pop();
            taskSize_--;
            // 如果依然有剩余任务，继续通知其它的线程执行任务
            if (taskQueue_.size() > 0)
            {
                notEmpty_.notify_all();
            }
            // 取出任务通知出去
            notFull_.notify_all();
        } // 作用域结束才释放锁，没释放锁的话，其他线程执行不了

        // 当前线程执行这个任务
        if (task != nullptr)
        {
            task->exec();
        }
        idleThreadSize_++;
        lastTime = std::chrono::high_resolution_clock().now();
    }
};


